package api

/*
#include <stdio.h>
#include <stdlib.h>
#include "include/tesseract/capi.h"
#include "include/leptonica/allheaders.h"
#cgo LDFLAGS: -lz -llzma -ltesseract -llept -lgif -ljpeg -lpng -lwebp  -ltiff  -lm -lstdc++
*/
import "C"
import (
	"errors"
	"fmt"
	"strings"
	"unsafe"

	"github.com/xlvector/dlog"
)

type Tesser struct {
	handle *C.struct_TessBaseAPI
	lang   string
	ipsm   C.TessPageSegMode
	psm    string
}

func NewTesser(lang string, psm string) *Tesser {
	t := &Tesser{
		lang: lang,
		psm:  psm,
		ipsm: C.PSM_AUTO_OSD,
	}

	if psm == "10" {
		dlog.Info("psm 10")
		t.ipsm = C.PSM_SINGLE_CHAR
	}
	handle := C.TessBaseAPICreate()
	//fmt.Printf("%#v\n", handle)
	if unsafe.Pointer(handle) == nil {
		return nil
	}

	t.handle = handle
	err := t.Init()
	if err != nil {
		return nil
	}

	return t
}

func (p *Tesser) SetLanguage(lang string) {
	p.lang = lang
}

func (p *Tesser) GetLanguage() string {
	return p.lang
}

func (p *Tesser) Init() error {
	clang := C.CString(p.lang)
	defer C.free(unsafe.Pointer(clang))

	//cpsm := C.CString(p.psm)
	//defer C.free(unsafe.Pointer(cpsm))

	//ret := C.TessBaseAPIInit2(p.handle, nil, clang, C.OEM_CUBE_ONLY)
	ret := C.TessBaseAPIInit3(p.handle, nil, clang)
	//fmt.Printf("%#v\n", ret)
	if ret != 0 {
		//fmt.Printf("error!")
		return errors.New("init fail!")
	}
	C.TessBaseAPISetPageSegMode(p.handle, p.ipsm)

	return nil
}

func (p *Tesser) SetWhiteList(v string) {
	//String whitelist = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
	cvar := C.CString(v)
	defer C.free(unsafe.Pointer(cvar))

	whitelist := C.CString("tessedit_char_whitelist")
	defer C.free(unsafe.Pointer(whitelist))

	C.TessBaseAPISetVariable(p.handle, whitelist, cvar)
}

func (p *Tesser) Close() {
	C.TessBaseAPIEnd(p.handle)

	p.handle = nil
	C.TessBaseAPIDelete(p.handle)
}

func (p *Tesser) RecognizeMem(img []byte) (string, error) {
	cimg := C.pixReadMem((*C.l_uint8)(unsafe.Pointer(&img[0])), C.size_t(len(img)))
	//fmt.Printf("%#v\n", img)
	if unsafe.Pointer(cimg) == nil {
		//fmt.Printf("%#v %#v\n", img, unsafe.Pointer(nil))
		return "", errors.New("read img fail!")
	}

	C.TessBaseAPISetImage2(p.handle, cimg)
	ret := C.TessBaseAPIRecognize(p.handle, nil)
	if ret != 0 {
		fmt.Printf("recog error!")
		return "", errors.New("read img fail!")
	}

	text := C.TessBaseAPIGetUTF8Text(p.handle)
	//fmt.Printf("text: %#v\n", C.GoString(text))

	return strings.TrimSpace(C.GoString(text)), nil

}

//cgo LDFLAGS: libs/libz.a libs/liblzma.a libs/libtesseract.a libs/liblept.a libs/libgif.a libs/libjpeg.a libs/libpng.a libs/libwebp.a  libs/libtiff.a  -lm -lstdc++
